import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_demo/generated/assets.dart';
import 'package:flutter_demo/pages/page_with_title.dart';
import 'package:flutter_demo/widgets/app_widgets.dart';

class FilterPage extends PageWithTitle {
  const FilterPage({super.key}) : super("滤镜(BackdropFilter、ImageFiltered、ColorFiltered)");

  @override
  List<Widget> buildContentWidgets(BuildContext context) {
    return const [
      PrimaryTitle("简介"),
      BodyText(
          "滤镜，用于对组件最终渲染内容进行一些效果调整，如模糊、变换等使用ImageFilter、"
              "如色彩调整等使用ColorFilter，Flutter针对不同的使用场景提供了以下滤镜组件，按需选"
              "择"),
      AppSpacer.large,
      _BlurExample(),
      AppSpacer.mini,
      UlItem("BackdropFilter"),
      BodyText("背景滤镜，对处于组件下方的绘制内容进行图像处理"),
      NoticeText(
          "使用背景滤镜需注意，必须采用ClipRect进行裁剪，因为它默认是对其下方的绘制内"
              "容拷贝副本进行图像处理，裁剪有助于提高计算效率并且不影响到其它区域"),
      NoticeText(
          "在列表中使用此组件，在滚动时会出现显示异常，因为滤镜效果计算量大，做不到实时"
              "更新，它在滚动时取消了滤镜效果"),
      LabelText("- filter Flutter提供了一些常用滤镜实现"),
      LabelText(
          "  - ImageFilter.blur 模糊（高斯模糊、毛玻璃效果，每个像素点参考周围的像"
              "素点颜色进行调整，一般权重比例是正态分布，越靠近像素点中心占比越高，参数是参考范围，"
              "越大则计算量越高，模糊效果越好，0则不参考）"),
      LabelText("  - ImageFilter.dilate 膨胀（表现为高亮度区域扩大）"),
      LabelText("  - ImageFilter.erode 腐蚀（表现为高亮度区域收缩）"),
      LabelText(
          "  - ImageFilter.matrix 矩阵变换（默认的原点是外层Stack组件左上角）"),
      LabelText("  - ImageFilter.compose 用于组合多种滤镜效果"),
      LabelText(
          "  - ColorFilter.mode 对每个像素点按照混合模式与目标颜色进行混合"),
      LabelText(
          "  - ColorFilter.matrix 对每个像素点的颜色值（RGBA）用矩阵进行变换，可以参考"),
      UrlLink("常用图像滤镜矩阵",
          "https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent"),
      LabelText("- child 子组件内容在拷贝的图像副本之外，不受滤镜影响"),
      AppSpacer.large,
      _ImageFilteredExample(),
      UlItem("ImageFiltered"),
      BodyText("图像滤镜，用于图像变换，对比背景滤镜，它只对子组件的内容起效果"),
      LabelText("- imageFilter 滤镜"),
      LabelText("- enable 是否启用滤镜"),
      LabelText("- child 要应用滤镜的子组件"),
      AppSpacer.large,
      _ColorFilteredExample(),
      UlItem("ColorFiltered"),
      BodyText(
          "色彩滤镜，用于像素颜色调整，对比背景滤镜，它只对子组件的内容起效果"),
      NoticeText(
          "- 我们知道ColorFilter其实也是ImageFilter，使用ImageFiltered来加载"
              "ColorFilter也可以实现，实际上两者实现上有差异："),
      NoticeText(
          "     - ColorFiltered 主要依赖图形库（skia）中的颜色混合、颜色矩阵相关接"
              "口实现，操作上更接近渲染管线的颜色合成阶段，性能开销小，建议优先使用"),
      NoticeText(
          "     - ImageFiltered 在图像光栅化之前生效，对屏幕上每个像素点进行（根据"
              "变换）纹理采样，若需要扭曲或者模糊效果，还需要对周围像素点采样后进行加权计算，它的性"
              "能开销更高"),
      LabelText("- colorFilter 滤镜"),
      LabelText("- child 要应用滤镜的子组件"),
    ];
  }
}

class _BlurExample extends StatelessWidget {
  const _BlurExample();

  @override
  Widget build(BuildContext context) {
    return UnconstrainedBox(
      alignment: Alignment.centerLeft,
      child: SizedBox(
        width: 300,
        height: 200,
        child: Stack(
          fit: StackFit.expand,
          children: [
            Text('0' * 10000),
            Column(
              children: [
                Row(
                  children: [
                    const Expanded(
                        child: SizedBox(
                          height: 100,
                        )),
                    Expanded(
                      child: ClipRect(
                        child: BackdropFilter(
                          filter: ImageFilter.blur(
                            sigmaX: 2.0,
                            sigmaY: 2.0,
                          ),
                          child: Container(
                            alignment: Alignment.center,
                            height: 100.0,
                            child: const Text('高斯模糊'),
                          ),
                        ),
                      ),
                    ),
                    Expanded(
                      child: ClipRect(
                        child: BackdropFilter(
                          filter: ImageFilter.dilate(
                            radiusX: 0.3,
                            radiusY: 0.3,
                          ),
                          child: Container(
                            alignment: Alignment.center,
                            height: 100.0,
                            child: const Text('膨胀(扩大亮区域)'),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                Row(
                  children: [
                    Expanded(
                      child: ClipRect(
                        child: BackdropFilter(
                          filter: ImageFilter.erode(
                            radiusX: 0.3,
                            radiusY: 0.3,
                          ),
                          child: Container(
                            alignment: Alignment.center,
                            height: 100.0,
                            child: const Text('腐蚀（收缩亮区域）'),
                          ),
                        ),
                      ),
                    ),
                    Expanded(
                      child: ClipRect(
                        child: BackdropFilter(
                          filter: ImageFilter.matrix(
                            (
                                //移动原点到当前组件中心
                                Matrix4.translationValues(150, 150, 0)
                                    //绕原点旋转90度
                                    *
                                    Matrix4.rotationZ(pi / 2)
                                    //原点复位
                                    *
                                    Matrix4.translationValues(
                                        -150, -150, 0))
                                .storage,
                          ),
                          child: Container(
                            alignment: Alignment.center,
                            height: 100.0,
                            child: const Text('应用矩阵变换'),
                          ),
                        ),
                      ),
                    ),
                    Expanded(
                      child: ClipRect(
                        child: BackdropFilter(
                          filter: ColorFilter.mode(
                            Theme
                                .of(context)
                                .colorScheme
                                .primary,
                            BlendMode.modulate,
                          ),
                          child: Container(
                            alignment: Alignment.center,
                            height: 100.0,
                            child: const Text('颜色滤镜'),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

class _ImageFilteredExample extends StatelessWidget {
  const _ImageFilteredExample();

  @override
  Widget build(BuildContext context) {
    return UnconstrainedBox(
      alignment: Alignment.centerLeft,
      child: SizedBox(
        width: 300,
        child: Column(
          children: [
            Row(
              children: [
                Expanded(
                  child: Image.asset(
                    Assets.imagesBenxi,
                    fit: BoxFit.contain,
                  ),
                ),
                Expanded(
                  child: ClipRect(
                    child: ImageFiltered(
                      imageFilter: ImageFilter.blur(
                        sigmaX: 3.0,
                        sigmaY: 3.0,
                      ),
                      child: Image.asset(
                        Assets.imagesBenxi,
                        fit: BoxFit.contain,
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: ClipRect(
                    child: ImageFiltered(
                      imageFilter: ImageFilter.dilate(
                        radiusX: 1,
                        radiusY: 1,
                      ),
                      child: Image.asset(
                        Assets.imagesBenxi,
                        fit: BoxFit.contain,
                      ),
                    ),
                  ),
                ),
              ],
            ),
            Row(
              children: [
                Expanded(
                  child: ClipRect(
                    child: ImageFiltered(
                      imageFilter: ImageFilter.erode(
                        radiusX: 1,
                        radiusY: 1,
                      ),
                      child: Image.asset(
                        Assets.imagesBenxi,
                        fit: BoxFit.contain,
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: ClipRect(
                    child: ImageFiltered(
                      imageFilter: ImageFilter.matrix(
                        (
                            //移动原点到当前组件中心
                            Matrix4.translationValues(50, 50, 0)
                                //绕原点旋转90度
                                *
                                Matrix4.rotationZ(pi / 2)
                                //原点复位
                                *
                                Matrix4.translationValues(-50, -50, 0))
                            .storage,
                      ),
                      child: Image.asset(
                        Assets.imagesBenxi,
                        fit: BoxFit.contain,
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: ClipRect(
                    child: ImageFiltered(
                      imageFilter: ImageFilter.matrix(
                        (Matrix4.translationValues(50, 0, 0)
                            //矩阵分左乘与右乘，这里按照顺序应用变换
                            //倾斜，参数是弧度角，atan根据正弦值反算弧度角
                            *
                            Matrix4.skewX(atan(-0.5)) *
                            Matrix4.diagonal3Values(0.5, 1, 1)
                            // *
                        )
                            .storage,
                      ),
                      child: Image.asset(
                        Assets.imagesBenxi,
                        fit: BoxFit.contain,
                      ),
                    ),
                  ),
                ),
              ],
            )
          ],
        ),
      ),
    );
  }
}

class _ColorFilteredExample extends StatelessWidget {
  const _ColorFilteredExample();

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const BodyText("颜色混合，以下为常用例子"),
        const NoticeText(
            "底层为我们的child渲染图像命名为dst，上层为我们的颜色图层命名为src"),
        const LabelText("- clear、src、dst 分别表示清理渲染图像、取src、取dst"),
        const LabelText("- srcOver、dstOver 表示交换图层位置，src在上、dst在上"),
        const LabelText(
            "- srcIn、dstIn 表示只取图层重叠部分的像素保留透明度，颜色来自src，颜色来自dst"),
        const LabelText(
            "- srcOut 取两者不重叠部分的像素保留透明度，颜色来自src"),
        const LabelText("- dstOut srcOut的反转"),
        const LabelText("- srcATop srcOver取重叠部分像素"),
        const LabelText("- dstATop srcATop的反转"),
        GridView.builder(
          shrinkWrap: true,
          physics: const NeverScrollableScrollPhysics(),
          itemCount: BlendMode.values.length,
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 4),
          itemBuilder: (context, index) {
            return AspectRatio(
              aspectRatio: 1,
              child: Column(
                children: [
                  ColorFiltered(
                    colorFilter: ColorFilter.mode(
                      const Color(0x80FF6D00),
                      BlendMode.values[index],
                    ),
                    child: const Icon(
                      Icons.ten_k,
                      size: 60,
                    ),
                  ),
                  Text(BlendMode.values[index].name)
                ],
              ),
            );
          },
        ),

        AppSpacer.large,
        const BodyText("官方颜色转换矩阵示例[反色，棕色，灰度]"),
        UnconstrainedBox(
          alignment: Alignment.centerLeft,
          child: SizedBox(
            width: 300,
            child: Column(
              children: [
                Row(
                  children: [
                    Expanded(
                     child: ColorFiltered(
                       colorFilter:const ColorFilter.matrix([
                         -1,  0,  0, 0, 255,
                         0, -1,  0, 0, 255,
                         0,  0, -1, 0, 255,
                         0,  0,  0, 1,   0,
                       ]),
                       child: Image.asset(
                         Assets.imagesBenxi,
                         fit: BoxFit.contain,
                       ),
                     ),
                    ),
                    Expanded(
                      child: ColorFiltered(
                        colorFilter:const ColorFilter.matrix([
                          0.393, 0.769, 0.189, 0, 0,
                          0.349, 0.686, 0.168, 0, 0,
                          0.272, 0.534, 0.131, 0, 0,
                          0,     0,     0,     1, 0,
                        ]),
                        child: Image.asset(
                          Assets.imagesBenxi,
                          fit: BoxFit.contain,
                        ),
                      ),
                    ),
                    Expanded(
                      child: ColorFiltered(
                        colorFilter:const ColorFilter.matrix([
                          0.2126, 0.7152, 0.0722, 0, 0,
                          0.2126, 0.7152, 0.0722, 0, 0,
                          0.2126, 0.7152, 0.0722, 0, 0,
                          0,      0,      0,      1, 0,
                        ]),
                        child: Image.asset(
                          Assets.imagesBenxi,
                          fit: BoxFit.contain,
                        ),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        )
      ],
    );
  }
}
